﻿using AngleSharp.Dom;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Playwright;
using System.Collections;
using TableTools.Handlers;
using TableTools.Models;

namespace TableTools.Services
{
    public class HtmlToTableService : ITableService, IAsyncDisposable
    {
        private readonly ILogger<HtmlToTableService> logger;
        private readonly IBrowserHandler browser;

        private IPage page;

        public HtmlToTableService(
            ILogger<HtmlToTableService> logger,
            IBrowserHandler browser)
        {
            this.logger = logger;
            this.browser = browser;
        }

        public async Task OpenAsync(string url)
        {
            page = await browser.GetPageAsync();

            await page.GotoAsync(url);
            await page.WaitForLoadStateAsync();
        }

        public async Task<TableResult> ToTableAsync(string url)
        {
            try
            {
                return await GetTablesAsync(page);
            }
            catch (Exception e)
            {
                logger.LogWarning(e, "生成table失败");
                return new TableResult();
            }
            finally
            {
                //await page.CloseAsync();
            }
        }

        private async Task<TableResult> GetTablesAsync(IPage page)
        {
            TableResult result = new TableResult();

            var tables = await page.QuerySelectorAllAsync("table");

            for (int i =0; i < tables.Count; i++)
            {
                var table = tables[i];
                var template = new TableTemplate();

                var thead = await table.QuerySelectorAsync("thead");
                if(thead != null)
                {
                    var tbody = await table.QuerySelectorAsync("tbody");
                    var trs = await tbody.QuerySelectorAllAsync("tr");
                    var tds = await thead.QuerySelectorAllAsync("th");
                    template.Table = new TableInfo(trs.Count, tds.Count);
                    for (int j = 0; j < tds.Count; j++)
                    {
                        var td = tds[j];
                        template.Table.Headers[j] = (await td.TextContentAsync()).Replace("\u200b", string.Empty);
                    }

                    for (int j = 0; j < template.Table.Row; j++)
                    {
                        var tr = trs[j];
                        tds = await tr.QuerySelectorAllAsync("td");
                        for (int k = 0; k < template.Table.Col; k++)
                        {
                            var td = tds[k];
                            template.Table.Rows[j][k] = (await td.TextContentAsync()).Replace("\u200b", string.Empty);
                        }
                    }
                }
                else
                {
                    var trs = await table.QuerySelectorAllAsync("tr");

                    var header = trs.FirstOrDefault();
                    var tds = await header.QuerySelectorAllAsync("td");
                    if (trs.Count > 1)
                    {
                        template.Table = new TableInfo(trs.Count - 1, tds.Count);
                        for (int j = 0; j < tds.Count; j++)
                        {
                            var td = tds[j];
                            template.Table.Headers[j] = (await td.TextContentAsync()).Replace("\u200b", string.Empty);
                        }

                        for (int j = 0; j < template.Table.Row; j++)
                        {
                            var tr = trs[j + 1];
                            tds = await tr.QuerySelectorAllAsync("td");
                            for (int k = 0; k < template.Table.Col; k++)
                            {
                                var td = tds[k];
                                template.Table.Rows[j][k] = (await td.TextContentAsync()).Replace("\u200b", string.Empty);
                            }
                        }
                    }
                    else if(trs.Count == 1)
                    {
                        if(i +1 < tables.Count)
                        {
                            table = tables[++i];
                            trs = await table.QuerySelectorAllAsync("tr");
                        }

                        template.Table = new TableInfo(trs.Count, tds.Count);
                        for (int j = 0; j < tds.Count; j++)
                        {
                            var td = tds[j];
                            template.Table.Headers[j] = (await td.TextContentAsync()).Replace("\u200b", string.Empty);
                        }

                        for (int j = 0; j < template.Table.Row; j++)
                        {
                            var tr = trs[j];
                            tds = await tr.QuerySelectorAllAsync("td");
                            for (int k = 0; k < template.Table.Col; k++)
                            {
                                var td = tds[k];
                                template.Table.Rows[j][k] = (await td.TextContentAsync()).Replace("\u200b", string.Empty);
                            }
                        }
                    }
                }

                result.Add(template);
            }

            return result;
        }

        public async ValueTask DisposeAsync()
        {
            if (page is not null)
            {
                await page.CloseAsync();
            }
        }
    }
}
